<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="../js/vue.js"></script>
    <title>总结Vue数据监测</title>
</head>
<!-- 
        Vue监视数据的原理:
            1. vue会监视data中所有层次的数据

            2. 如何监测对象中的数据?
                通过setter实现监视,且要在new Vue创建实例时就传入要监测的数据
                (1). 对象中后追加的属性,Vue默认不做响应式处理
                (2). 如需给后添加的属性做响应式,请使用如下API
                        Vue.set(target, propertyName/index, value)或
                        vm.$set(target, propertyName/index, value)

            3. 如何监测数组中的数据?
                通过包裹数组更新元素的方法实现,本质就是做了两件事:
                    (1).调用原生对应的方法对数组进行更新
                    (2).重新解析模板,进而更新页面

            4.在Vue修改数组中的某个元素一定要用如下方法:
                        1.使用这些API:push()、shift()、unshift()、pop()、splice()、sort()、reverse()
                        2.Vue.set() 或 vm.$set()

            特别注意:Vue.set()和 vm.$set()不能给vm或者vm的根数据对象添加属性

            有些特殊的数组方法,返回一个新的数组能不能用?我们这样用不久可以了吗,本质就是改的响应属性的属性值
            this.student.hobby=this.student.hobby.filter((h)=>{
                return h!='抽烟'
            })

 -->

<body>
    <div id="root">
        <button @click="student.age++">年龄+1岁</button>
        <button @click="addSex">添加性别属性，默认值，男</button>
        <button @click="addFriend">在列表首位添加一个朋友</button>
        <button @click="updateFirstName">修改第一个朋友名字为：张三</button>
        <button @click="addHobby">添加一个爱好</button>
        <button @click="updateFirstHobby">修改第一个爱好为：开车</button>

        <h1>个人信息</h1>
        <h3>姓名：{{student.name}}</h3>
        <h3>年龄：{{student.age}}</h3>
        <h3>性别：{{student.sex}}</h3>
        <h3>爱好：</h3>
        <ul>
            <li v-for="(item,index) in student.hobby" :key="index">
                {{item}}
            </li>
        </ul>
        <h3>朋友们：</h3>
        <ul>
            <li v-for="(item,index) in student.friends" :key="index">
                姓名：{{item.name}}，年龄：{{item.age}}
            </li>
        </ul>
    </div>
    <script>
        Vue.config.productionTip = false; //以阻止vue在启动时生成生产提示
        const Vm = new Vue({
            el: "#root",
            data: {
                student: {
                    name: "张名师",
                    age: 18,
                    hobby: ['抽烟', '喝酒', '烫头'],
                    friends: [{
                            name: "小冯",
                            age: 18
                        },
                        {
                            name: "老勇",
                            age: 18
                        }
                    ]
                }
            },
            methods: {
                addSex() {
                    // 对象新增的属性不是响应式的，我们要响应式添加
                    // 参数3个（目标   属性/索引位置   内容）
                    this.$set(this.student, 'sex', '男')
                },
                addFriend() {
                    // 方法一：直接使用Vue对数组包装的7个方法
                    this.student.friends.unshift({
                        name: 'zhang',
                        age: 18
                    })
                    // 1.考虑一个问题，我们现在改动friends中对象某个属性的时候，我们可以看到会重新解析模板，因为数组下对象属性已经是响应式了一旦改动肯定会重新解析模板

                    // 2.那么我们新添加friend对象时候,通过数组原始7个方法肯定能触发重新解析模板,这里边属性是响应式吗?改动新添加对象里边的属性呢?会重新解析模板吗?
                    // 答案:可以并且是响应式的(可以去看控制台打印下friend,看是否有setter和getter如果有就是响应式的,就可以重新解析模板)


                },
                updateFirstName() {
                    // 我们不是修改了数组内容吗?为什么不用改变原数组的7个方法

                    // 有误区了,一定要知道我们改的是谁?
                    // 1.对象:比如添加(除了set()响应式添加)删除对象属性不能触发重新解析模板方法;对于已有的对象属性改动其值可引起模板重新解析因为存在响应式属性
                    // 2.对于数组：必须使用包装的7个改变原数组的方法才可以解析模板内容，通过赋值的方法不可以，因为Vue包装了其改变原数组的方法里边增加了更新模板的方法

                    // 从下边我们可以知道肯定是改动的时候对象内容,所以应该对应对象规则，改的的已有属性name，是响应式，改动了当然引起模板重新解析
                    this.student.friends[0].name = "张三"
                },
                addHobby() {
                    this.student.hobby.push("学习")
                },
                updateFirstHobby() {
                    // 这里我们为什么不直接 this.student.hobby[0]="玩游戏"？
                    // 我们处理的是谁？数组，数组直接赋值不会触发模板重新解析

                    // 方法一:利用Vue包装的改变原数组的方法
                    // this.student.hobby.splice(0, 1, "玩游戏")

                    // 方法二:利用Vue的API中set函数
                    this.$set(this.student.hobby, 0, '玩游戏')
                }
            }
        })
    </script>

</body>

</html>